package com.sheng.project.study.genericity;

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

/**
 * @author liusheng
 * @date 2023/07/06
 */
interface Demo1T1 {

}

interface Demo1T2 {

}

public class Demo1<T1, T2 extends Integer, T3 extends Demo1T1 & Demo1T2> {

    /**
     * 类中定义泛型变量
     * 泛型变量需要在类名后面的括号中定义
     * 每个类中可以定义多个泛型变量，多个泛型变量之间用逗号隔开
     * 泛型变量可以通过extends关键字指定上边界，上边界可以对泛型变量起到了限定的作用，
     * 上边界可以指定0到多个，多个之间需要用&符号隔开，如果不指定上边界，默认上边界为Object类型
     * <p>
     * <a href="https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933878&idx=1&sn=bebd543c39d02455456680ff12e3934b&chksm=88621dc8bf1594de6b50a760e4141b80da76442ba38fb93a91a3d18ecf85e7eee368f2c159d3&token=799820369&lang=zh_CN&scene=21#wechat_redirect">...</a>
     *
     * @param args
     */
    public static void main(String[] args) {
        // getTypeParameters 用于获取声明的泛型变量类型清单，返回当前类上定义的泛型变量类型列表
        TypeVariable<Class<Demo1>>[] typeParameters = Demo1.class.getTypeParameters();
        for (TypeVariable<Class<Demo1>> typeParameter : typeParameters) {
            // 获取在源码中定义时的名字，如：class Test<K extend Person>就是K；class Test1<T>中就是T。
            System.out.println("变量名称：" + typeParameter.getName());
            // 获取声明该泛型变量的原始类型
            // 例如：class Test<K extend Person>中的K为泛型变量，这个泛型变量时Test类定义的时候声明的
            // 说明如果调用getGenericDeclaration方法返回的就是Test对应的Class对象。
            System.out.println("这个变量是在哪声明的：" + typeParameter.getGenericDeclaration());
            // 获取泛型变量类型的上边界，如果未明确什么上边界默认为Object
            // 例如：class Test<K extend Person>中K的上边界只有一个，是Person；
            // 而class Test<T extend List & Iterable>中T的上边界有2个，是List和Iterable
            Type[] bounds = typeParameter.getBounds();
            System.out.println("这个变量上边界数量：" + bounds.length);
            System.out.println("这个变量上边界清单：");
            for (Type bound : bounds) {
                System.out.println(bound.getTypeName());
            }
            System.out.println("---------------------------------");
        }
    }
}
